<?php

namespace app\common\service;

use app\admin\model\KnscyOrderLogs;
use app\admin\model\KnscyOrders;
use app\admin\model\KnscyOrderTicket;
use app\admin\model\KnscyRedpack;
use app\admin\model\KnscyRedpackAgent;
use app\admin\model\KnscyTicketOut;
use think\facade\Cache;
use think\facade\Db;

class OrderService
{
    /**
     * 生成一个订单号
     */
    public static function order_gen_id()
    {
        /*生成一个 订单号*/
        $i = rand(1, 9999);
        do {
            if (9999 == $i) {
                $i = 1;
            }
            $i++;
            $order_sn = date('ymdHis') . str_pad($i, 4, '0', STR_PAD_LEFT);
            $row = KnscyOrders::where('order_no', $order_sn)->find();
        } while ($row);
        return $order_sn;
    }

    /**
     * 生成一个额优惠券编号
     * @return string
     */
    public static function redpack_no()
    {
        /*生成一个 订单号*/
        $i = rand(1, 9999);
        do {
            if (9999 == $i) {
                $i = 1;
            }
            $i++;
            $order_sn = 'CON' . date('ymd') . str_pad($i, 4, '0', STR_PAD_LEFT);
            $row = KnscyRedpack::where('redpack_no', $order_sn)->find();
        } while ($row);
        return $order_sn;
    }

    /**
     * 生成一个额优惠券编号
     * @return string
     */
    public static function agent_sn()
    {
        /*生成一个 订单号*/
        $i = rand(1, 9999);
        do {
            if (9999 == $i) {
                $i = 1;
            }
            $i++;
            $order_sn = 'AN' . date('ymd') . str_pad($i, 4, '0', STR_PAD_LEFT);
            $row = KnscyRedpackAgent::where('agent_sn', $order_sn)->find();
        } while ($row);
        return $order_sn;
    }
    public static function order_use_discount($agent_sn, $user_id, $order )
    {
        $info = KnscyRedpackAgent::where('agent_sn', $agent_sn)
            ->where('user_id', $user_id)
            ->where('is_used',0)
            ->find();
        if($info){
            $update = [
                'is_used'=> 1,
                'ticket_sn' => $order['order_no'], //用来记录哪个订单使用了优惠券
                'use_time' => date('Y-m-d H:i:s' ),
            ];
           KnscyRedpackAgent::update($update, ['id'=>$info['id']]);

            //创建日志
            KnscyOrderLogs::create([
                'uniacid' => $order['uniacid'],
                'order_id' => $order['id'],
                'order_no' => $order['order_no'],
                'tag' => 'order.orderUseDiscount',
                'content' => '使用优惠券 => '.$agent_sn ."，可抵扣金额 => ".$info['discount'] ."，本订单抵扣金额 => ".$order['discount_money'],
            ]);
        }

        return true;
    }
    /**
     * 获取用户优惠券的信息
     * @param $agent_sn
     * @param $user_id
     */
    public static function get_discount_detail($agent_sn, $user_id)
    {
        if(!$agent_sn || !$user_id) return 0;

        $info = KnscyRedpackAgent::where('agent_sn', $agent_sn)
            ->where('user_id', $user_id)
            ->where('is_used',0)
            ->find();
        if(empty($info)){
            return 0;
        }

        return $info['discount'] ?? 0;
    }
    /**
     * 返回当前可用的总折扣金额
     */
    public static function get_discount($user_id = 0)
    {
        $data = [];
        if(!$user_id){
            return $data;
        }
        $data = KnscyRedpackAgent::withoutGlobalScope(['uniacid'])
            ->alias('a')->where('a.status', 1)
             ->where('a.redpack_type', 1) //优惠券类型
            ->where('a.is_used', 0) //未用
            ->whereTime('a.end_time', '>=', date('Y-m-d 23:59:59'))
            //已用或 失效的 券
            ->where('user_id', $user_id)
            ->join(KnscyRedpack::getTable()." p", "p.redpack_no= a.redpack_no")
            ->order(Db::raw('a.sort=0,a.sort asc,a.id desc'))
            ->field("a.*,p.title,p.subtitle,p.tag,p.describe")
            ->select();

        return $data;

    }

    /**
     * 判断当前的价格如果是0 就直接完成订单状态
     * @param $order
     * @return void
     */
    public static function directBuy($order)
    {
        $pay_money = max(0, $order['order_money'] - $order['discount_money']);
        if ($pay_money == 0 && $order['status_label'] == 'unpaid') {
            $orm = KnscyOrders::where('order_no', $order['order_no'])->find();
            $orm->status_label = 'process'; //
            $orm->order_status = KnscyOrders::label2Status('process');
            $orm->save();

            OrderService::changeStatus($orm, $order);
        }
    }

    public static function changeStatus($order, $oldOrder, $tag = 'order.createOrder.change')
    {
        $logs = "";
        $fields = [
            'status_label' => '订单状态',
            'order_status' => '订单进度',
            'is_refund' => '是否退款'
        ];
        //记录状态变更

        foreach ($fields as $k => $v) {
            if ($oldOrder[$k] != $order[$k]) {
                $logs .= "，{$v}从 " . $oldOrder[$k] . ' => ' . $order[$k];
            }
        }
        $infos = [
            'order.createOrder.change' => '订单无需支付',
            'order.qrcode.check' => '订单核销成功',
            'order.refundOrder.change' => '订单退款成功'
        ];

        //创建日志
        KnscyOrderLogs::create([
            'order_id' => $order['id'],
            'order_no' => $order['order_no'],
            'tag' => $tag,
            'content' => ($infos[$tag] ?? '') . $logs,
        ]);
        //如果订单已经支付了创建 出票记录
        if ($order['status_label'] == 'process') {
            OrderService::usedTicketOut($order);
        }
        //如果订单退款 ，删除出票记录
        if ($order['status_label'] == 'refund') {
            OrderService::deleteTicketOut($order, 'order.refund');
        }
        //如果订单取消
        if ($order['status_label'] == 'cancel') {
            OrderService::deleteTicketOut($order, 'order.cancel');
        }

    }

    /**
     * 前后台 都用到这个地方
     * 退款的时候删除出票记录
     * @param $order
     * @return void
     */

    public static function deleteTicketOut($order, $tag = 'admin.order.refund')
    {
        if ($order['status_label'] !== 'refund' && $order['status_label'] !== 'cancel') {
            return;
        }

        $sns = KnscyTicketOut::where('order_no', $order['order_no'])
            //->where('sort', -1)
            ->column('ticket_sn');
        KnscyTicketOut::destroy(function ($query) use ($order) {
            $query->where('order_no', $order['order_no']);
            // ->where('sort', -1);//未使用的可以删除
        });
        $tags = [
            'order.refund' => '订单退款',
            'order.cancel' => '订单取消',
            'admin.order.refund' => '后台订单退款',
            'admin.order.cancel' => '后台订单取消',
        ];
        if (!empty($sns)) {
            //创建日志
            KnscyOrderLogs::create([
                'order_id' => $order['id'],
                'order_no' => $order['order_no'],
                'tag' => 'order.refund',
                'content' => ($tags[$tag] ?? '') . '，消票(卡)成功，票NO => ' . implode(',', $sns),
            ]);
        }

    }

    /**
     * 订单支付后，更改出票的信息为有效;
     * 注意要在wxapp的 payResult里面实现同样功能，修改出票为有效
     * @param $order
     * @return false|void
     */
    public static function usedTicketOut($order)
    {
        if ($order['status_label'] !== 'process')
            return false;
        $sns = KnscyTicketOut::where('order_no', $order['order_no'])->column('ticket_sn');
        KnscyTicketOut::update(['sort' => 0, 'start_time' => date('Y-m-d H:i:s')],
            ['order_no' => $order['order_no']]);

        //创建日志
        KnscyOrderLogs::create([
            'order_id' => $order['id'],
            'order_no' => $order['order_no'],
            'tag' => 'order.process',
            'content' => '订单生效，出票(卡)成功，票NO => ' . implode(',', $sns),
        ]);
    }

    /**
     * 根据订单创建门票 或者 次卡 年卡
     * 每个订单购买的数量 进行创建
     * 前后台 都用到这个地方
     * @param $order
     * @return boolean
     */
    public static function createTicketOut($order, $ticket)
    {

        //检查是否创建过
        $has = KnscyTicketOut::where('order_no', $order['order_no'])->select();
        if (!$has->isEmpty())
            return false;
        //创建数量
        $ticket_json = json_decode($ticket['ticket_json'], true);
        $count = max(1, $ticket['buy_num']);
        $peoples = is_array($ticket['people_json']) ? $ticket['people_json'] : json_decode($ticket['people_json'], true);
        $out = [];
        for ($i = 1; $i <= $count; $i++) {
            $people = $peoples[0] ?? "";
            if (isset($peoples[$i])) {
                $people = $peoples[$i];
            }
            $data = [
                'uniacid' => $order['uniacid'],
                'user_id' => $order['user_id'],
                'order_no' => $order['order_no'],
                'ticket_sn' => $order['order_no'] . $i,
                'ticket_id' => $ticket['ticket_id'],
                'ticket_type' => $ticket['ticket_type'],
                'ticket_title' => $ticket['ticket_title'],
                'ticket_subtitle' => $ticket['ticket_subtitle'],
                'select_day' => $ticket['select_day'],
                'total_count' => $ticket_json ['use_count'] ?? 1,
                'price' => $ticket_json ['price'],
                'people_info' => json_encode($people),
                'orgin_price' => $ticket_json ['orgin_price'],
                'sort' => -1, //出票但是因为订单没有付款所以，表示票无效
                'create_time' => time(),
                'update_time' => time(),
            ];
            if ($ticket['ticket_type'] == 1) {
                //门票只能用一次
                $data['total_count'] = 1;
            }
            //门票或者次卡

            $out[] = $data;
        }
        if (count($out) > 0) {
            KnscyTicketOut::insertAll($out);
            $sns = array_column($out, 'ticket_sn');
            //创建日志
            KnscyOrderLogs::create([
                'order_id' => $order['id'],
                'order_no' => $order['order_no'],
                'tag' => 'order.createTicket',
                'content' => '订单创建，创建出票/卡信息，票NO => ' . implode(',', $sns),
            ]);
        }

        return true;

    }

    public static function isCanRefund($order)
    {
        //订单能退款= 是否可退款&& 已经在线支付=3 && 当前状态status_label=process待出行
        if ($order['can_refund'] == 1
            && $order['pay_status'] == 3
            && $order['status_label'] == 'process'
            && $order['is_refund'] == 0
        ) {
            return 1;
        }
        return 0;
    }

    /**
     * 处理退款的方法
     * @param $order
     * @return bool
     */
    public static function orderDoRefund($order)
    {
        if (!OrderService::isCanRefund($order)) {
            return false;
        }
        $orm = KnscyOrders::find($order['id']);
        $oldOrder = clone $orm;
        //修改状态
        $orm->status_label = 'refund';
        $orm->order_status = KnscyOrders::label2Status('refund');
        $orm->is_refund = 1;
        $orm->save();
        return OrderService::changeStatus($orm, $oldOrder, 'order.refundOrder.change');
    }

    /**
     * 后台修改订单的状态
     * @param KnscyOrders $order 当前订单数据
     * @param KnscyOrders $oldOrder 旧的订单数据 状态值unpaid,process,completed,refund,cancel
     * @return bool
     */
    public static function admin_change_order($order, $oldOrder)
    {
        if (!$order || !$oldOrder) {
            return true;
        }
        $logs = "";
        $fields = [
            'status_label' => '订单状态',
            'discount_money' => '折扣金额',
            'remark' => '备注信息',
            'status' => '状态',
            'can_refund' => '是否可退',
            'need_check' => '是否需换票',
            'sort' => '排序'
        ];
        //记录状态变更

        foreach ($fields as $k => $v) {
            if ($oldOrder[$k] != $order[$k]) {
                $logs .= "，{$v}从 " . $oldOrder[$k] . ' => ' . $order[$k];
            }
        }


        //创建日志
        KnscyOrderLogs::create([
            'order_id' => $order['id'],
            'order_no' => $order['order_no'],
            'tag' => 'admin.change_order_status',
            'content' => '后台编辑' . (!empty($logs) ? $logs : '，字段数据未做修改'),
            'admin_id' => session('admin.id') ?? 0
        ]);

        //如果订单已经支付了创建 出票记录
        if ($order['status_label'] == 'process') {
            OrderService::usedTicketOut($order);
        }
        //如果订单退款 ，删除出票记录
        if ($order['status_label'] == 'refund') {
            OrderService::deleteTicketOut($order, 'admin.order.refund');
        }
        //如果订单取消 ，删除出票记录
        if ($order['status_label'] == 'cancel') {
            OrderService::deleteTicketOut($order, 'admin.order.cancel');
        }

        return true;
    }

    /**
     * 把到期没有核销的订单自动完成
     */
    public static function autoCompletedExpireOrder()
    {

        $cache = Cache::get('autoCompletedExpireOrderCacheKey');
        if ($cache == 1) {
            return true;
        } else {
            Cache::set('autoCompletedExpireOrderCacheKey', 1, 30);
        }
        $list = KnscyOrders::withoutGlobalScope(['uniacid'])->alias('o')
            ->where('o.status_label', 'process')
            ->leftjoin(KnscyOrderTicket::getTable() . " t", "t.order_id=o.id")
            ->where('o.uniacid', WeginService::getUniacid())
            ->whereTime('t.select_day', '<', date('Y-m-d'))
            ->limit(5)
            ->select();

        $status = KnscyOrders::label2Status('completed');
        $status_label = 'completed';
        $logs = [];
        foreach ($list as $k => $v) {

            $content = ",订单状态从 " . $v['status_label'] . " => $status_label ";
            $content .= ",订单进度从 " . $v['order_status'] . " => $status ";
            $logs[] = [
                'uniacid' => $v['uniacid'],
                'order_id' => $v['id'],
                'order_no' => $v['order_no'],
                'tag' => 'auto.completed.order',
                'content' => '订单系统处理' . $content,
                'create_time' => time(),
                'update_time' => time(),
            ];
        }
        if ($logs) {

            $ids = array_column($list->toArray(), 'id');
            KnscyOrders::whereIn('id', $ids)->update(['status_label' => $status_label, 'order_status' => $status]);
            //这里用了微擎的返回tablename方法；
            Db::table(tablename('knscy_order_logs'))->insertAll($logs);
            Cache::delete('autoCompletedExpireOrderCacheKey');
            unset($logs);
        }
        return true;
    }

    /**
     * 取消1小时 不支付的订单
     *
     */
    public static function autoCancelExpireOrder()
    {

        $cache = Cache::get('autoCancelExpireOrderCacheKey');
        if ($cache == 1) {
            return true;
        } else {
            Cache::set('autoCancelExpireOrderCacheKey', 1, 30);
        }
        $list = KnscyOrders::where('status_label', 'unpaid')
            ->whereIn('order_status', [0, 1])
            ->whereTime('create_time', '<', strtotime('-1 hour'))
            ->limit(5)
            ->select();

        $logs = [];
        foreach ($list as $k => $v) {

            $content = ",订单状态从 " . $v['status_label'] . " => cancel ";
            $content .= ",订单进度从 " . $v['order_status'] . " => 0 ";
            $logs[] = [
                'uniacid' => $v['uniacid'],
                'order_id' => $v['id'],
                'order_no' => $v['order_no'],
                'tag' => 'auto.cancel.order',
                'content' => '订单系统处理' . $content,
                'create_time' => time(),
                'update_time' => time(),
            ];
        }
        if ($logs) {

            $status = KnscyOrders::label2Status('cancel');
            $ids = array_column($list->toArray(), 'id');
            KnscyOrders::whereIn('id', $ids)->update(['status_label' => 'cancel', 'order_status' => $status]);
            //这里用了微擎的返回tablename方法；
            Db::table(tablename('knscy_order_logs'))->insertAll($logs);
            Cache::delete('autoCancelExpireOrderCacheKey');
            unset($logs);
        }

    }
}